`include "timescale.v"

module onu_rs(
	input 		   Gtx_clk					,//used only in GMII mode
	input 		   Tx_en					,
	input 		   Tx_er					,
	input  [7:0]   Txd_mac						,

	input  	   	   Rx_clk					,
	input 	   	   Rx_dv					,
	input	   	   Rx_er					,
	input  [7:0]   Rxd						,

	input 		   Col						,	
	input	   	   Crs						,

	input 		   reset,

	input  [15:0]  LocalLLID,
	
	//output 
	// output reg [7:0] Txd,
	output reg [7:0]   Txd,
	output reg  [7:0] Rxd_mac,
	output 		   Rx_dv_mac
);

// wire 	  [15:0]  LocalLLID;
// assign 			  LocalLLId   = 16'h0003;

wire 			  rx_pre_crc_err;
reg 	  [15:0]  LLID;
// assign 			  LLID 		  = 16'h0003;

//LLID filter
reg 	  [3:0]   RxByteCnt;
// assign 			  cnt_latch   = Rx_dv & (Rxd == 8'hD5);
wire 			  rx_llid_valid;
reg 			  rx_llid_valid_inner;


// assign 			  Rxd_mac 	  = (RxByteCnt==4'd7 & ~rx_llid_valid) ? 8'h00 : Rxd;
// assign 			  Rx_dv_mac   = (RxByteCnt>=4'd7 & ~rx_llid_valid) ? 1'b0 : Rx_dv;
assign 			  Rx_dv_mac   = (RxByteCnt>=4'd7 & ~rx_llid_valid) ? 1'b0 : Rx_dv;
assign 			  rx_llid_valid = rx_llid_valid_inner | ((LLID == LocalLLID | LLID[15]) & ~rx_pre_crc_err);
  
always@(*)
begin
  Rxd_mac = 8'hxx;
  if(Rx_dv)
  begin
	if(RxByteCnt < 4'd7)
	  Rxd_mac = 8'h55;
	else if(RxByteCnt == 4'd7)
	  Rxd_mac = 8'hD5;
	else if(rx_llid_valid)
	  Rxd_mac = Rxd;
  end
end
// reg 	  [7:0]   crc8;
// wire 			  init_crc;
// assign 			  init_crc 	  = RxByteCnt == 3'd1;
// always@(posedge Rx_clk)
// begin
//   if(init_crc)
// 	$crc8_init(crc8);
//   else if(RxByteCnt >= 3'd2)
// 	$crc8_calc(crc8);
// end

always@(posedge Rx_clk or posedge reset)
begin
  if(reset)
	RxByteCnt <= 4'd0;
  else if(~Rx_dv)
	RxByteCnt <= 4'd0;
  else if(RxByteCnt < 4'd8)
	RxByteCnt <= RxByteCnt + 4'd1;			//the max value is 7
end

wire 	  [7:0]   rx_crc;

always@(posedge Rx_clk or posedge reset)
begin
  if(reset)
	rx_llid_valid_inner <= 1'b0;
  else if(~Rx_dv)
	rx_llid_valid_inner <= 1'b0;
  else if(RxByteCnt == 3'd2)
	rx_llid_valid_inner <= Rxd == 8'hD5;
  else if(RxByteCnt == 3'd5)
  begin
	LLID[15:8] <= Rxd;
  end
  // rx_llid_valid <= rx_llid_valid & (Rxd == LLID[15:8]);
  else if(RxByteCnt == 3'd6)
  begin
	LLID[7:0] <= Rxd;
	// rx_llid_valid <= rx_llid_valid & (Rxd == LLID[7:0]);
  end
  else if(RxByteCnt == 3'd7)
	rx_llid_valid_inner <= (LLID == LocalLLID | LLID[15]) & ~rx_pre_crc_err;
end


crc8 U_rx_crc8(
	.reset					(reset),
	.clk					(Rx_clk),
	.enable					(1'b1),
	.init					(RxByteCnt==3'd1),
	.Data					(Rxd),
	.Crc					(rx_crc),
	.CrcErr					(),
	.PreCrcErr				(rx_pre_crc_err)
	);

	
// wire 			  enable_rx_llid_crc;
// always@(posedge Rx_clk or posedge reset)
// begin
  
// end

// always@(*)
// begin
//   if( (RxByteCnt == 3'd2) && (Rxd == LLID[))
// 	Txd = 8'hD5;
//   else if(RxByteCnt == 3'd5)
// 	Txd = LLID[15:8];
//   else if(RxByteCnt == 3'd6)
// 	Txd = LLID[7:0];
//   else if(RxByteCnt == 3'd7)
// 	// Txd = CRC8;
// 	Txd = 8'h12;
//   else 
// 	Txd = Txd_mac;
// end
	  




//LLID adder
reg 	  [3:0]   TxByteCnt;
always@(posedge Gtx_clk or posedge reset)
begin
  if(reset)
	TxByteCnt <= 4'd0;
  else if(~Tx_en)
	TxByteCnt <= 4'd0;
  else if(TxByteCnt < 4'd8)
	TxByteCnt <= TxByteCnt + 4'd1;			//the max value is 7
end


wire 	  [7:0]   tx_crc;
crc8 U_tx_crc8(
	.reset					(reset),
	.clk					(Gtx_clk),
	.enable					(1'b1),
	.init					(TxByteCnt == 4'd1),
	.Data					(Txd),
	.Crc					(tx_crc),
	.CrcErr					(),
	.PreCrcErr				()
	);


// wire 	  [7:0]   CRC8;
// assign 			  CRC8 		  = 8'h12;
//mux
always@(*)
begin
  if(TxByteCnt == 4'd2)
	Txd = 8'hD5;
  else if(TxByteCnt == 4'd5)
	Txd = LLID[15:8];
  else if(TxByteCnt == 4'd6)
	Txd = LLID[7:0];
  else if(TxByteCnt == 4'd7)
	Txd = {tx_crc[0], tx_crc[1], tx_crc[2], tx_crc[3], tx_crc[4], tx_crc[5], tx_crc[6], tx_crc[7]};	//
  else 
	Txd = Txd_mac;
end

// assign 			  Txd 		  = Txd_mac;

// initial begin
//   Gtx_clk = 0;
//   forever #4 Gtx_clk = ~Gtx_clk;
// end

endmodule